package com.fulihui.wgj.service.qrcode;


import com.alibaba.dubbo.config.annotation.Service;
import com.fulihui.common.builder.rpc.RpcResultBuilder;
import com.fulihui.common.constants.QrcodeConstants;
import com.fulihui.common.conv.BeanConv;
import com.fulihui.common.enums.CustomMsgTypeEnum;
import com.fulihui.common.error.Errors;
import com.fulihui.common.error.InvokeServiceException;
import com.fulihui.common.request.rpc.AppRequest;
import com.fulihui.common.result.rpc.BaseResult;
import com.fulihui.common.result.rpc.SimpleResult;
import com.fulihui.common.util.Base64Utils;
import com.fulihui.common.util.ConditionValidator;
import com.fulihui.common.util.PlatformUtil;
import com.fulihui.weixinsdk.WeixinSDK;
import com.fulihui.weixinsdk.request.qrcode.CreateQrcodeRequest;
import com.fulihui.weixinsdk.result.qrcode.CreateQrcodeResult;
import com.fulihui.wgj.dal.mybatis.domain.LabelsInfo;
import com.fulihui.wgj.dal.mybatis.domain.WxParamQrcodeInfo;
import com.fulihui.wgj.dal.mybatis.domain.WxQrcodeEventStat;
import com.fulihui.wgj.dal.mybatis.domain.WxQrcodeReplyInfo;
import com.fulihui.wgj.dal.mybatis.domain.WxQrcodeScanEvent;
import com.fulihui.wgj.dal.mybatis.repository.LabelsInfoRepository;
import com.fulihui.wgj.dal.mybatis.repository.WxMaterialRepository;
import com.fulihui.wgj.dal.mybatis.repository.WxParamQrcodeInfoRepository;
import com.fulihui.wgj.dal.mybatis.repository.WxQrcodeEventStatRepository;
import com.fulihui.wgj.dal.mybatis.repository.WxQrcodeReplyInfoRepository;
import com.fulihui.wgj.dal.mybatis.repository.WxQrcodeScanEventRepository;
import com.fulihui.wgj.facade.dto.WxParamQrcodeInfoDTO;
import com.fulihui.wgj.facade.dto.WxQrcodeEventStatDTO;
import com.fulihui.wgj.facade.dto.WxQrcodeEventStatDetailDTO;
import com.fulihui.wgj.facade.dto.WxQrcodeReplyInfoDTO;
import com.fulihui.wgj.facade.request.qrcode.WxParamQrcodeSaveRequest;
import com.fulihui.wgj.facade.request.qrcode.WxQrcodeEventStatRequest;
import com.fulihui.wgj.facade.request.qrcode.WxQrcodeEventStatSqlRequest;
import com.fulihui.wgj.facade.request.qrcode.WxQrcodeInfoQueryRequest;
import com.fulihui.wgj.facade.request.qrcode.WxQrcodePageQueryRequest;
import com.fulihui.wgj.facade.request.qrcode.WxQrcodeQueryRequest;
import com.fulihui.wgj.facade.request.qrcode.WxQrcodeReplyDeleteRequest;
import com.fulihui.wgj.facade.request.qrcode.WxQrcodeReplyQueryOneRequest;
import com.fulihui.wgj.facade.request.qrcode.WxQrcodeReplyRequest;
import com.fulihui.wgj.facade.request.qrcode.WxQrcodeScanEventRequest;
import com.fulihui.wgj.facade.request.qrcode.WxQrcodeStatDetailPageQueryRequest;
import com.fulihui.wgj.facade.request.qrcode.WxQrcodeStatDetailQueryRequest;
import com.fulihui.wgj.facade.result.qrcode.WxQrcodePageResult;
import com.fulihui.wgj.facade.result.qrcode.WxQrcodeStatDetailPageResult;
import com.fulihui.wgj.facade.service.qrcode.WxParamQrcodeService;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 渠道二维码相关Service
 *
 * @author wang_wx
 * @date 2018-07-09
 */
@Component
@Service(interfaceClass = WxParamQrcodeService.class, version = "1.0.0", timeout = 5000)
public class WxParamQrcodeServiceImpl implements WxParamQrcodeService {

    private static final Logger LOGGER = LoggerFactory.getLogger(WxParamQrcodeServiceImpl.class);

    @Autowired
    WxQrcodeReplyInfoRepository wxQrcodeReplyInfoRepository;

    @Autowired
    WxQrcodeEventStatRepository wxQrcodeEventStatRepository;

    @Autowired
    WxParamQrcodeInfoRepository wxParamQrcodeInfoRepository;

    @Autowired
    WxQrcodeScanEventRepository wxQrcodeScanEventRepository;

    @Autowired
    WxMaterialRepository wxMaterialRepository;

    @Autowired
    LabelsInfoRepository labelsInfoRepository;

    @Autowired
    PlatformUtil platformUtil;

    @Autowired
    WeixinSDK weixinSDK;

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Override
    public SimpleResult<WxQrcodeReplyInfoDTO> queryOneReplyInfo(WxQrcodeReplyQueryOneRequest request) throws InvokeServiceException {
        ConditionValidator.validate(request);
        String appId = request.getAppId();
        Long id = request.getId();
        String sceneStr = request.getSceneStr();
        if (Objects.isNull(id) && StringUtils.isBlank(sceneStr)) {
            return RpcResultBuilder.failSimple(Errors.WxSubscribeReplyError.ID_AND_SCENESTR_CANNOT_BE_ALL_EMPTY);
        }
        WxQrcodeReplyInfo wxQrcodeReplyInfo;
        if (Objects.nonNull(id)) {
            wxQrcodeReplyInfo = wxQrcodeReplyInfoRepository.queryById(id);
        } else {
            WxQrcodeReplyInfo replyInfoQuery = new WxQrcodeReplyInfo();
            replyInfoQuery.setAppId(appId);
            replyInfoQuery.setSceneStr(sceneStr);
            wxQrcodeReplyInfo = wxQrcodeReplyInfoRepository.queryOne(replyInfoQuery);
        }
        WxQrcodeReplyInfoDTO infoDTO = null;
        if (Objects.nonNull(wxQrcodeReplyInfo)) {
            infoDTO = BeanConv.copy(wxQrcodeReplyInfo, WxQrcodeReplyInfoDTO.class);
            if (CustomMsgTypeEnum.text.getCode().equals(infoDTO.getMsgType())) {
                // 是文本内容 需base64解码
                infoDTO.setContent(Base64Utils.decode(infoDTO.getContent()));
            }
//            if (!CustomMsgTypeEnum.text.getCode().equals(infoDTO.getMsgType())) {
//                // 不是文本内容 查询素材信息 填充content
//                String mediaId = infoDTO.getContent();
//                if (StringUtils.isNotBlank(mediaId)) {
//                    WxMaterial wxMaterial = wxMaterialRepository.queryById(mediaId);
//                    if (Objects.nonNull(wxMaterial)) {
//                        WxMaterialDTO materialDTO = BeanConv.copy(wxMaterial, WxMaterialDTO.class);
//                        infoDTO.setContent(JSONObject.toJSONString(materialDTO));
//                    }
//                }
//            } else {
//                // 是文本内容 需base64解码
//                infoDTO.setContent(Base64Utils.decode(infoDTO.getContent()));
//            }
        }
        LOGGER.info("infoDTO = {}", infoDTO);
        return RpcResultBuilder.succSimple(infoDTO);
    }

    @Override
    public BaseResult saveReplyInfo(WxQrcodeReplyRequest request) throws InvokeServiceException {
        ConditionValidator.validate(request);
        Long id = request.getId();
        Integer count;
        if (Objects.isNull(id)) {
            // 新增
            WxQrcodeReplyInfo replyInfoQuery = new WxQrcodeReplyInfo();
            replyInfoQuery.setAppId(request.getAppId());
            replyInfoQuery.setSceneStr(request.getSceneStr());
            WxQrcodeReplyInfo wxQrcodeReplyInfo = wxQrcodeReplyInfoRepository.queryOne(replyInfoQuery);
            if (Objects.nonNull(wxQrcodeReplyInfo)) {
                return RpcResultBuilder.fail(Errors.Commons.RECORD_ALREADY_EXISTS);
            }
            WxQrcodeReplyInfo qrcodeReplyInfo = BeanConv.copy(request, WxQrcodeReplyInfo.class);
            if (CustomMsgTypeEnum.text.getCode().equals(qrcodeReplyInfo.getMsgType())) {
                // 是文本内容 进行编码
                qrcodeReplyInfo.setContent(Base64Utils.encode(qrcodeReplyInfo.getContent()));
            }
            count = wxQrcodeReplyInfoRepository.saveSelective(qrcodeReplyInfo);
        } else {
            WxQrcodeReplyInfo wxQrcodeReplyInfo = wxQrcodeReplyInfoRepository.queryById(id);
            if (Objects.isNull(wxQrcodeReplyInfo)) {
                return RpcResultBuilder.fail(Errors.Commons.RECORD_NOT_EXISTS);
            }
            WxQrcodeReplyInfo qrcodeReplyInfo = BeanConv.copy(request, WxQrcodeReplyInfo.class);
            qrcodeReplyInfo.setGmtModified(new Date());
            if (CustomMsgTypeEnum.text.getCode().equals(qrcodeReplyInfo.getMsgType())) {
                // 是文本内容 进行编码
                qrcodeReplyInfo.setContent(Base64Utils.encode(qrcodeReplyInfo.getContent()));
            }
            count = wxQrcodeReplyInfoRepository.updateSelective(qrcodeReplyInfo);
        }
        return count > 0 ? RpcResultBuilder.succ() : RpcResultBuilder.fail(Errors.Commons.SAVE_FAILED);
    }

    @Override
    public BaseResult deleteReplyInfo(WxQrcodeReplyDeleteRequest request) throws InvokeServiceException {
        ConditionValidator.validate(request);
        WxQrcodeReplyInfo wxQrcodeReplyInfo = wxQrcodeReplyInfoRepository.queryById(request.getId());
        if (Objects.isNull(wxQrcodeReplyInfo)) {
            return RpcResultBuilder.fail(Errors.Commons.RECORD_NOT_EXISTS);
        }
        Integer count = wxQrcodeReplyInfoRepository.deleteById(request.getId());
        return count > 0 ? RpcResultBuilder.succ() : RpcResultBuilder.fail(Errors.Commons.DELETE_FAILED);
    }

    @Override
    public BaseResult saveStat(WxQrcodeEventStatRequest request) throws InvokeServiceException {
        ConditionValidator.validate(request);
        WxQrcodeEventStat eventStat = BeanConv.copy(request, WxQrcodeEventStat.class);
        WxQrcodeEventStat eventStatQuery = new WxQrcodeEventStat();
        eventStatQuery.setAppId(eventStat.getAppId());
        eventStatQuery.setSceneId(eventStat.getSceneId());
        eventStatQuery.setGmtAttention(eventStat.getGmtAttention());
        WxQrcodeEventStat exist = wxQrcodeEventStatRepository.queryOne(eventStatQuery);
        if (Objects.nonNull(exist)) {
            return RpcResultBuilder.fail(Errors.Commons.RECORD_ALREADY_EXISTS);
        }
        Integer count = wxQrcodeEventStatRepository.saveSelective(eventStat);
        return count > 0 ? RpcResultBuilder.succ() : RpcResultBuilder.fail(Errors.Commons.SAVE_FAILED);
    }

    @Override
    public BaseResult saveStatBySql(WxQrcodeEventStatSqlRequest request) throws InvokeServiceException {
        ConditionValidator.validate(request);
        String appId = request.getAppId();
        String sceneId = request.getSceneId();
        String gmtAttention = request.getGmtAttention();
        WxQrcodeEventStat eventStat = new WxQrcodeEventStat();
        eventStat.setAppId(appId);
        eventStat.setGmtAttention(gmtAttention);
        eventStat.setSceneId(sceneId);

        WxQrcodeEventStat eventStatQuery = new WxQrcodeEventStat();
        eventStatQuery.setAppId(appId);
        eventStatQuery.setSceneId(sceneId);
        eventStatQuery.setGmtAttention(gmtAttention);
        WxQrcodeEventStat exist = wxQrcodeEventStatRepository.queryOne(eventStatQuery);
        if (Objects.nonNull(exist)) {
            return RpcResultBuilder.fail(Errors.Commons.RECORD_ALREADY_EXISTS);
        }
        // 复杂SQL执行时间长 异步
        threadPoolTaskExecutor.execute(() -> wxQrcodeEventStatRepository.saveStatBySql(eventStat));
        return RpcResultBuilder.succ();
    }

    @Override
    public SimpleResult<List<WxQrcodeEventStatDTO>> queryStatistics(WxQrcodeQueryRequest request) throws InvokeServiceException {
        ConditionValidator.validate(request);
        List<WxParamQrcodeInfo> wxParamQrcodeInfos = wxParamQrcodeInfoRepository.queryListByRequest(request);
        List<WxQrcodeEventStatDTO> dtoList = null;
        if (!CollectionUtils.isEmpty(wxParamQrcodeInfos)) {
            dtoList = BeanConv.copy(wxParamQrcodeInfos, WxQrcodeEventStatDTO.class);
            List<String> sceneIds = Lists.newArrayList();
            dtoList.forEach(wxQrcodeEventStatDTO -> sceneIds.add(wxQrcodeEventStatDTO.getSceneStr()));
            // 查询统计
            List<WxQrcodeEventStat> wxQrcodeEventStats = wxQrcodeEventStatRepository.sumEventStat(sceneIds, request);
            if (!CollectionUtils.isEmpty(wxQrcodeEventStats)) {
                for (WxQrcodeEventStatDTO wxQrcodeEventStatDTO : dtoList) {
                    String appId = wxQrcodeEventStatDTO.getAppId();
                    String sceneStr = wxQrcodeEventStatDTO.getSceneStr();
                    // 查询是否有回复内容
                    WxQrcodeReplyInfo replyInfoQuery = new WxQrcodeReplyInfo();
                    WxQrcodeReplyInfo replyInfo = wxQrcodeReplyInfoRepository.queryOne(replyInfoQuery);
                    if (Objects.nonNull(replyInfo)) {
                        wxQrcodeEventStatDTO.setReplyInfoId(replyInfo.getId());
                    }

                    // 合并统计信息
                    for (WxQrcodeEventStat wxQrcodeEventStat : wxQrcodeEventStats) {
                        if (StringUtils.equals(appId, wxQrcodeEventStat.getAppId())
                                && StringUtils.equals(sceneStr, wxQrcodeEventStat.getSceneId())) {
                            wxQrcodeEventStatDTO.setScanCount(wxQrcodeEventStat.getScanOldUserCount() + wxQrcodeEventStat.getSubscribeCount());
                            wxQrcodeEventStatDTO.setSubscribeCount(wxQrcodeEventStat.getSubscribeCount());
                            break;
                        }
                    }
                }
            }
        }
        return RpcResultBuilder.succSimple(dtoList);
    }

    @Override
    public WxQrcodePageResult pageQueryStatistics(WxQrcodePageQueryRequest request) throws InvokeServiceException {
        ConditionValidator.validate(request);
        // 分页查询基础信息
        PageInfo<WxParamQrcodeInfo> pageInfo = wxParamQrcodeInfoRepository.queryPageListByRequest(request);
        long total = pageInfo.getTotal();
        List<WxParamQrcodeInfo> pageInfoList = pageInfo.getList();
        WxQrcodePageResult wxQrcodePageResult = RpcResultBuilder.succPageResult(WxQrcodePageResult.class, pageInfo.getPageNum(), pageInfo.getPageSize(), (int) total);
        if (!CollectionUtils.isEmpty(pageInfoList)) {
            List<WxQrcodeEventStatDTO> dtoList = BeanConv.copy(pageInfoList, WxQrcodeEventStatDTO.class);
            List<String> sceneIds = Lists.newArrayList();
            dtoList.forEach(wxQrcodeEventStatDTO -> {
                sceneIds.add(wxQrcodeEventStatDTO.getSceneStr());
                // 查询是否有回复内容
                WxQrcodeReplyInfo replyInfoQuery = new WxQrcodeReplyInfo();
                replyInfoQuery.setAppId(wxQrcodeEventStatDTO.getAppId());
                replyInfoQuery.setSceneStr(wxQrcodeEventStatDTO.getSceneStr());
                WxQrcodeReplyInfo replyInfo = wxQrcodeReplyInfoRepository.queryOne(replyInfoQuery);
                if (Objects.nonNull(replyInfo)) {
                    wxQrcodeEventStatDTO.setReplyInfoId(replyInfo.getId());
                }
            });
            // 查询统计
            List<WxQrcodeEventStat> wxQrcodeEventStats = wxQrcodeEventStatRepository.sumEventStat(sceneIds, request);
            if (!CollectionUtils.isEmpty(wxQrcodeEventStats)) {
                for (WxQrcodeEventStatDTO wxQrcodeEventStatDTO : dtoList) {
                    String appId = wxQrcodeEventStatDTO.getAppId();
                    String sceneStr = wxQrcodeEventStatDTO.getSceneStr();

                    wxQrcodeEventStatDTO.setScanCount(0L);
                    wxQrcodeEventStatDTO.setSubscribeCount(0L);
                    // 合并统计信息
                    for (WxQrcodeEventStat wxQrcodeEventStat : wxQrcodeEventStats) {
                        if (StringUtils.equals(appId, wxQrcodeEventStat.getAppId())
                                && StringUtils.equals(sceneStr, wxQrcodeEventStat.getSceneId())) {
                            wxQrcodeEventStatDTO.setScanCount(wxQrcodeEventStat.getScanOldUserCount() + wxQrcodeEventStat.getSubscribeCount());
                            wxQrcodeEventStatDTO.setSubscribeCount(wxQrcodeEventStat.getSubscribeCount());
                            break;
                        }
                    }
                }
            }
            wxQrcodePageResult.setValue(dtoList);
        }
        return wxQrcodePageResult;
    }

    @Override
    public SimpleResult<List<WxQrcodeEventStatDetailDTO>> queryDetailStatistics(WxQrcodeStatDetailQueryRequest request) throws InvokeServiceException {
        ConditionValidator.validate(request);
        List<WxQrcodeEventStat> wxQrcodeEventStats = wxQrcodeEventStatRepository.queryDetailStat(request);
        List<WxQrcodeEventStatDetailDTO> detailDTOS = null;
        if (!CollectionUtils.isEmpty(wxQrcodeEventStats)) {
            detailDTOS = BeanConv.copy(wxQrcodeEventStats, WxQrcodeEventStatDetailDTO.class);
        }
        return RpcResultBuilder.succSimple(detailDTOS);
    }

    @Override
    public WxQrcodeStatDetailPageResult pageQueryDetailStatistics(WxQrcodeStatDetailPageQueryRequest request) throws InvokeServiceException {
        ConditionValidator.validate(request);
        PageInfo<WxQrcodeEventStat> pageInfo = wxQrcodeEventStatRepository.pageQueryDetailStat(request);
        long total = pageInfo.getTotal();
        WxQrcodeStatDetailPageResult result = RpcResultBuilder.succPageResult(WxQrcodeStatDetailPageResult.class, pageInfo.getPageNum(), pageInfo.getPageSize(), Math.toIntExact(total));
        if (total > 0) {
            result.setValue(BeanConv.copy(pageInfo.getList(), WxQrcodeEventStatDetailDTO.class));
        }
        return result;
    }

    @Override
    @Transactional(value = "mysqlTransactionManager", rollbackFor = Exception.class)
    public SimpleResult<WxParamQrcodeInfoDTO> saveParamQrcodeInfo(WxParamQrcodeSaveRequest saveRequest) throws InvokeServiceException {
        ConditionValidator.validate(saveRequest);

        WxParamQrcodeInfo qrcodeInfoQuery = new WxParamQrcodeInfo();
        qrcodeInfoQuery.setAppId(saveRequest.getAppId());
        qrcodeInfoQuery.setSceneStr(saveRequest.getSceneStr());
        WxParamQrcodeInfo queryOne = wxParamQrcodeInfoRepository.queryOne(qrcodeInfoQuery);
        if (Objects.nonNull(queryOne)) {
            return RpcResultBuilder.failSimple(Errors.WxParamQrcodeError.WECHAT_QR_CODE_ID_ALREADY_EXISTS);
        }

        CreateQrcodeResult qrcodeResult = createQrcode(saveRequest);
        if (Objects.isNull(qrcodeResult)) {
            return RpcResultBuilder.failSimple(Errors.WxParamQrcodeError.WECHAT_QR_CODE_FAILED);
        }

        WxParamQrcodeInfo qrcodeInfo = BeanConv.copy(saveRequest, WxParamQrcodeInfo.class);
        qrcodeInfo.setTicket(qrcodeResult.getTicket());
        qrcodeInfo.setUrl(qrcodeResult.getUrl());
        qrcodeInfo.setGmtModified(new Date());
        Integer count = wxParamQrcodeInfoRepository.saveSelective(qrcodeInfo);
        WxParamQrcodeInfoDTO infoDTO = null;
        if (count > 0) {
            WxParamQrcodeInfo qrcodeInfoQuery2 = new WxParamQrcodeInfo();
            qrcodeInfoQuery2.setAppId(saveRequest.getAppId());
            qrcodeInfoQuery2.setSceneStr(saveRequest.getSceneStr());
            WxParamQrcodeInfo queryOne2 = wxParamQrcodeInfoRepository.queryOne(qrcodeInfoQuery);
            infoDTO = BeanConv.copy(queryOne2, WxParamQrcodeInfoDTO.class);
        }

        if (StringUtils.isNotBlank(saveRequest.getContent()) && StringUtils.isNotBlank(saveRequest.getMsgType())) {
            // 有回复内容 - 插入关联表
            WxQrcodeReplyInfo qrcodeReplyInfo = new WxQrcodeReplyInfo();
            qrcodeReplyInfo.setAppId(saveRequest.getAppId());
            qrcodeReplyInfo.setSceneStr(saveRequest.getSceneStr());
            qrcodeReplyInfo.setMsgType(saveRequest.getMsgType());
            //避免文本有emoji表情需要base64编码
            if (CustomMsgTypeEnum.text.getCode().equals(saveRequest.getMsgType())) {
                qrcodeReplyInfo.setContent(Base64Utils.encode(saveRequest.getContent()));
            } else {
                qrcodeReplyInfo.setContent(saveRequest.getContent());
            }
            qrcodeReplyInfo.setGmtModified(new Date());
            wxQrcodeReplyInfoRepository.saveSelective(qrcodeReplyInfo);
        }

        return RpcResultBuilder.succSimple(infoDTO);
    }

    /**
     * 调用sdk生成渠道二维码
     *
     * @param request
     * @return
     */
    CreateQrcodeResult createQrcode(WxParamQrcodeSaveRequest request) {
        String cache = platformUtil.get(request.getAppId());
        if (StringUtils.isNotBlank(cache)) {
            String accessToken = cache;
            CreateQrcodeRequest createQrcodeRequest = new CreateQrcodeRequest();
            createQrcodeRequest.setAccess_token(accessToken);
            createQrcodeRequest.setAction_name(QrcodeConstants.QR_LIMIT_SCENE);
            Map<String, Map<String, String>> actionInfo = Maps.newHashMap();
            Map<String, String> paramMap = Maps.newHashMap();
            paramMap.put("scene_str", request.getSceneStr());
            actionInfo.put("scene", paramMap);
            createQrcodeRequest.setAction_info(actionInfo);
            CreateQrcodeResult createQrcodeResult;
            try {
                createQrcodeResult = weixinSDK.invokeService(createQrcodeRequest);
                return createQrcodeResult;
            } catch (Exception e) {
                LOGGER.error("weixinSDK createQrcode error" + e);
            }
        }
        return null;
    }

    @Override
    public SimpleResult<WxParamQrcodeInfoDTO> queryParamQrcodeInfo(WxQrcodeInfoQueryRequest request) throws InvokeServiceException {
        ConditionValidator.validate(request);
        WxParamQrcodeInfo qrcodeInfoQuery = new WxParamQrcodeInfo();
        qrcodeInfoQuery.setAppId(request.getAppId());
        qrcodeInfoQuery.setSceneStr(request.getSceneStr());
        WxParamQrcodeInfo exist = wxParamQrcodeInfoRepository.queryOne(qrcodeInfoQuery);
        WxParamQrcodeInfoDTO qrcodeInfoDTO = null;
        if (Objects.nonNull(exist)) {
            qrcodeInfoDTO = BeanConv.copy(exist, WxParamQrcodeInfoDTO.class);
        }
        return RpcResultBuilder.succSimple(qrcodeInfoDTO);
    }

    @Override
    public SimpleResult<List<WxParamQrcodeInfoDTO>> queryParamQrcodeInfoByAppId(AppRequest request) throws InvokeServiceException {
        ConditionValidator.validate(request);
        WxParamQrcodeInfo qrcodeInfoQuery = new WxParamQrcodeInfo();
        qrcodeInfoQuery.setAppId(request.getAppId());
        List<WxParamQrcodeInfo> wxParamQrcodeInfos = wxParamQrcodeInfoRepository.queryByWhere(qrcodeInfoQuery);
        List<WxParamQrcodeInfoDTO> dtos = null;
        if (!CollectionUtils.isEmpty(wxParamQrcodeInfos)) {
            dtos = BeanConv.copy(wxParamQrcodeInfos, WxParamQrcodeInfoDTO.class);
        }
        return RpcResultBuilder.succSimple(dtos);
    }

    @Override
    public BaseResult saveScanEvent(WxQrcodeScanEventRequest request) throws InvokeServiceException {
        ConditionValidator.validate(request);
        WxQrcodeScanEvent scanEvent = BeanConv.copy(request, WxQrcodeScanEvent.class);
        Integer count = wxQrcodeScanEventRepository.saveSelective(scanEvent);
        return count > 0 ? RpcResultBuilder.succ() : RpcResultBuilder.fail(Errors.Commons.SAVE_FAILED);
    }

    @Override
    public SimpleResult<List<WxParamQrcodeInfoDTO>> querySceneHasLabel(AppRequest request) throws InvokeServiceException {
        ConditionValidator.validate(request);
        List<WxParamQrcodeInfo> paramQrcodeInfos = wxParamQrcodeInfoRepository.queryByExample(buildExample4WxParamQrcode(request));
        List<WxParamQrcodeInfoDTO> infoDTOS = null;
        if (!CollectionUtils.isEmpty(paramQrcodeInfos)) {
            infoDTOS = BeanConv.copy(paramQrcodeInfos, WxParamQrcodeInfoDTO.class);
            infoDTOS.forEach(infoDTO -> {
                String sceneDescribe = infoDTO.getSceneDescribe();
                String channelLabel = infoDTO.getChannelLabel();
                LabelsInfo labelsInfo = labelsInfoRepository.queryById(channelLabel);
                if (Objects.nonNull(labelsInfo)) {
                    infoDTO.setChannelName(labelsInfo.getLabelName() + "(" + sceneDescribe + ")");
                }
            });
        }
        LOGGER.info("infoDTOS={}", request);
        return RpcResultBuilder.succSimple(infoDTOS);
    }

    Example buildExample4WxParamQrcode(AppRequest request) {
        Example example = new Example(WxParamQrcodeInfo.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("appId", request.getAppId());
        criteria.andNotEqualTo("channelLabel", "");
        criteria.andIsNotNull("channelLabel");
        return example;
    }
}
